package com.blvtphan.tipocketclubs.gui;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.View.OnClickListener;
import android.view.animation.ScaleAnimation;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Toast;

import com.blvtphan.tipocketclubs.R;
import com.blvtphan.tipocketclubs.abstracts.AbstractMapFragment;
import com.blvtphan.tipocketclubs.adapter.InfoWindowOfferAdapter;
import com.blvtphan.tipocketclubs.adapter.NearbyItemAdapter;
import com.blvtphan.tipocketclubs.custom.CustomButton;
import com.blvtphan.tipocketclubs.custom.CustomTextView;
import com.blvtphan.tipocketclubs.model.CacheBitmap;
import com.blvtphan.tipocketclubs.model.PlaceDetailModel;
import com.blvtphan.tipocketclubs.model.RewardsModel;
import com.blvtphan.tipocketclubs.util.Constants;
import com.blvtphan.tipocketclubs.util.GeneralUtils;
import com.blvtphan.tipocketclubs.widget.CustomProgressDialog;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap.InfoWindowAdapter;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

public class NearbySearchActivity extends AbstractMapFragment implements ConnectionCallbacks, OnConnectionFailedListener{

	LocationListener ll;
	LocationManager lm;
	private ListView mLstViewItem;
	private CustomTextView mTxtNoResult;
	private List<PlaceDetailModel> mLstItemNearby;
	private CustomButton mBtnExpand;
	private FrameLayout mFrameMap;
	private LinearLayout mLLMap;
	private boolean isExpand = false;
	
	private double myLat, myLng;
	private LocationClient mLocationClient;
	
	private final static int NEARBY = 40000;
	
//	private static final LocationRequest REQUEST = LocationRequest.create()
//            .setInterval(5000)         // 5 seconds
//            .setFastestInterval(16)    // 16ms = 60fps
//            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		map.setMyLocationEnabled(true);
		
		lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		
		setUpLocationClientIfNeeded();
		mLocationClient.connect();
		initView();
	}
	
	@Override
	protected void onResume() {
//		if(mLocationClient==null)
//			mLocationClient.connect();
		setLocationListener();
		Log.i("SearchNearby", "onResume");
		super.onResume();
	}
	
	@Override
	protected void onPause() {
		super.onPause();
		if(ll!=null)
			lm.removeUpdates(ll);
		if (mLocationClient != null) {
            mLocationClient.disconnect();
        }
		Log.i("SearchNearby", "onPause");
	}
	
	private void setUpLocationClientIfNeeded() {
        if (mLocationClient == null) {
            mLocationClient = new LocationClient(
                    mContext,
                    this,  // ConnectionCallbacks
                    this); // OnConnectionFailedListener
        }
    }
	
	@SuppressWarnings("unchecked")
	private void initData() {
		mLstItemNearby = new ArrayList<PlaceDetailModel>();
		try {
			mLstItemNearby = (List<PlaceDetailModel>)GeneralUtils
					.bytes2Object(getIntent().getByteArrayExtra(Constants.NearbySearchExtras.LIST_PLACES));
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	private void initListView(final List<PlaceDetailModel> lstResult) {
		
		NearbyItemAdapter adapter = new NearbyItemAdapter(mContext, lstResult);
		mLstViewItem.setAdapter(adapter);
		mLstViewItem.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> adapter, View view, int pos, long id) {
				Intent intent = new Intent(mContext, PlaceDetailsActivity.class);
				
				intent.putExtra(Constants.PlaceDetailExtras.ADDRESS, lstResult.get(pos).getAddress());
				intent.putExtra(Constants.PlaceDetailExtras.LAT, lstResult.get(pos).getLat());
				intent.putExtra(Constants.PlaceDetailExtras.LNG, lstResult.get(pos).getLng());
				intent.putExtra(Constants.PlaceDetailExtras.NAME, lstResult.get(pos).getName());
				intent.putExtra(Constants.PlaceDetailExtras.LOGO, lstResult.get(pos).getMarchantLogo());
				
				List<RewardsModel> lstRewardsModel = new ArrayList<RewardsModel>();
				lstRewardsModel = lstResult.get(pos).getLstRewards();
				try{
					intent.putExtra(Constants.PlaceDetailExtras.LST_PLACE_REWARDS, 
							GeneralUtils.object2Bytes(lstRewardsModel));
				} catch (IOException e){
					e.printStackTrace();
				}
				
				startActivity(intent);
			}
		});
	}
	
	@Override
	protected void onStart() {
		super.onStart();
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		lm.removeUpdates(ll);
	}
	
	private void moveToMyLocation() {
		
		checkGPSStatus();
		
		myLat = mLocationClient.getLastLocation().getLatitude();
	    myLng = mLocationClient.getLastLocation().getLongitude();
		
	    LatLng coor = new LatLng(myLat, myLng);
	    map.moveCamera(CameraUpdateFactory.newLatLngZoom(coor, 20));
	    map.animateCamera(CameraUpdateFactory.zoomTo(15), 2000, null);
	}
	
	private void checkGPSStatus() {
		if(!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
			GeneralUtils.showToastMessage(mContext, getResources().getString(R.string.mess_turn_on_gps), Toast.LENGTH_LONG);
		} 
	}
	
	private void setLocationListener() {
		ll = new LocationListener() {
			@Override
			public void onLocationChanged(Location location) {
				Toast.makeText(getApplicationContext(),
	                    location.getLatitude() + " " + location.getLongitude(),
	                    Toast.LENGTH_LONG).show();

	            map.addMarker(new MarkerOptions()
	                    .position(new LatLng(location.getLatitude(), location.getLongitude()))
	                    .title("my position")
	                    .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));

	            map.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(
	                    location.getLatitude(), location.getLongitude()), 15.0f));
	            Log.i("Location", "location: "+location.getLatitude()+":"+location.getLongitude());
	            
			}

			@Override
			public void onProviderDisabled(String arg0) {
			}

			@Override
			public void onProviderEnabled(String arg0) {
			}

			@Override
			public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
			}
			
		};
		lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);
	}
	
	@SuppressLint("NewApi") 
	private void doSearchNearby() {
		
		AsyncTask<Void, Void, Void> doSearchTask = new AsyncTask<Void, Void, Void>() {
			
			private CustomProgressDialog progressDialog;
			private List<PlaceDetailModel> lstPlaceSearchResult;
			
			@Override
			protected Void doInBackground(Void... params) {
				for(int i=0;i<mLstItemNearby.size();i++) {
					float[] result = new float[3];
					Location.distanceBetween(myLat, myLng, mLstItemNearby.get(i).getLat(), mLstItemNearby.get(i).getLng(), result);
					if(result!=null && result.length>1) {
						if(result[0] <= NEARBY) {
							setImageMarkerForLocation(mLstItemNearby.get(i));
							mLstItemNearby.get(i).setDistance(String.valueOf(result[0]));
							lstPlaceSearchResult.add(mLstItemNearby.get(i));
						}
					}
				}
				
				return null;
			}
			
			@Override
			protected void onPreExecute() {
				progressDialog = new CustomProgressDialog(mContext,
						getResources().getString(R.string.calculating));
				initData();
				lstPlaceSearchResult = new ArrayList<PlaceDetailModel>();
				super.onPreExecute();
			}
			
			@Override
			protected void onPostExecute(Void result) {
				progressDialog.hideDialog();
				if(lstPlaceSearchResult!=null && lstPlaceSearchResult.size()>0) {
					GeneralUtils.showToastMessage(mContext, getResources().getString(R.string.mess_search_found).replace("{0}", 
							String.valueOf(lstPlaceSearchResult.size())), Toast.LENGTH_LONG);
				}
				if(lstPlaceSearchResult==null || lstPlaceSearchResult.size()==0) {
					mTxtNoResult.setVisibility(View.VISIBLE);
				} else {
					mTxtNoResult.setVisibility(View.GONE);
					initListView(lstPlaceSearchResult);
				}
				super.onPostExecute(result);
			}
		};
		
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
			doSearchTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
		} else {
			doSearchTask.execute();
		}
	}
	
	@SuppressLint("NewApi") 
	private void setImageMarkerForLocation(final PlaceDetailModel placeModel) {
		AsyncTask<Void, Void, CacheBitmap> task = new AsyncTask<Void, Void, CacheBitmap>() {

			@Override
			protected CacheBitmap doInBackground(Void... params) {

				Bitmap tmp = MainActivity.mCache
						.getBitmapFromMemCache(placeModel.getMarchantLogo());
				if (tmp != null) {
					CacheBitmap bt = new CacheBitmap();
					bt.setKey(placeModel.getMarchantLogo());
					bt.setBitmap(tmp);
					Log.d("Using Image Memory Cache :", "FYI");
					return bt;
				} else {
					Log.d("Downloading Images :", "FYI");
					return GeneralUtils.downloadImageWithCache(mContext, placeModel.getMarchantLogo());
				}
			}

			@Override
			protected void onPostExecute(CacheBitmap result) {
				if (result != null) {
					MainActivity.mCache.addBitmapToMemoryCache(result.getKey(), result.getBitmap());
					LatLng coor = new LatLng(placeModel.getLat(), placeModel.getLng());
					
					infoWindow = getLayoutInflater().inflate(R.layout.location_info_window, null);
					
					View markerBlue = LayoutInflater.from(mContext).inflate(R.layout.marker_location, null);
					ImageView locationLogo = (ImageView) markerBlue.findViewById(R.id.img_location_logo);
					locationLogo.setImageBitmap(result.getBitmap());
					markerBlue.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 
							MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
					markerBlue.layout(0, 0, markerBlue.getWidth(), markerBlue.getHeight());
					Bitmap locationMarkerBm = Bitmap.createBitmap(markerBlue.getMeasuredWidth(), 
							markerBlue.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
					
					Canvas canvas = new Canvas(locationMarkerBm);
					markerBlue.draw(canvas);
					
					String lstStrOffers = "";
					for(int i=0;i<placeModel.getLstRewards().size();i++) {
						lstStrOffers+=placeModel.getLstRewards().get(i).getTitle()+"<;>";
					}
					
					map.addMarker(new MarkerOptions().position(coor)
							.title(placeModel.getMarchantLogo() + "<;>" + placeModel.getName() + "<;>" + placeModel.getAddress())
							.snippet(lstStrOffers)
							.icon(BitmapDescriptorFactory.fromBitmap(Bitmap.createScaledBitmap(locationMarkerBm,
									 100, 100, false))));
					map.setInfoWindowAdapter(new CustomInfoAdapter());
					markerBlue.setDrawingCacheEnabled(false);
				}
			}
		};

		if (Build.VERSION.SDK_INT >= 11) {
			task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
		} else {
			task.execute();
		}
	}
	
	private View infoWindow;
	
	class CustomInfoAdapter implements InfoWindowAdapter {

		@Override
		public View getInfoContents(Marker marker) {
			String[] arrNameAdd = marker.getTitle().split("<;>");
			
			CustomTextView placeName = (CustomTextView)infoWindow.findViewById(R.id.txt_info_place_name);
			if(arrNameAdd[1]!=null)
				placeName.setText(arrNameAdd[1]);
			CustomTextView placeAddress = (CustomTextView)infoWindow.findViewById(R.id.txt_info_place_address);
			if(arrNameAdd[2]!=null)
				placeAddress.setText(arrNameAdd[2]);
			
			ImageView imageLogo = (ImageView)infoWindow.findViewById(R.id.img_info_place_logo);
			if(arrNameAdd[0]!=null) {
				imageLogo.setImageBitmap(MainActivity.mCache.getBitmapFromMemCache(arrNameAdd[0]));
			} else {
				imageLogo.setBackgroundResource(R.drawable.cancham);
			}
			
			CustomTextView noOfOffer = (CustomTextView)infoWindow.findViewById(R.id.txt_info_no_of_offer);
			String[] lstOffers = marker.getSnippet().split("<;>");
			if(lstOffers!=null && lstOffers.length>0) {
				noOfOffer.setText(getResources().getString(R.string.text_info_num_of_offer).replace("{0}", String.valueOf(lstOffers.length)));
				LinearLayout contentOffer = (LinearLayout)infoWindow.findViewById(R.id.ll_info_offer_content);
				contentOffer.removeAllViews();
				for(int i=0;i<lstOffers.length;i++) {
					InfoWindowOfferAdapter offerItem = new InfoWindowOfferAdapter(mContext, lstOffers[i]);
					contentOffer.addView(offerItem);
				}
			}
			
			return infoWindow;
		}

		@Override
		public View getInfoWindow(Marker marker) {
			return null;
		}
		
	}

	@Override
	public void onConnectionFailed(ConnectionResult arg0) {
		GeneralUtils.showToastMessage(mContext, getResources().getString(R.string.mess_connect_location_fail)
				, Toast.LENGTH_SHORT);
	}

	@Override
	public void onConnected(Bundle arg0) {
		// TODO Auto-generated method stub
		moveToMyLocation();
		doSearchNearby();
	}

	@Override
	public void onDisconnected() {
		
	}

	@Override
	public int getContentViewId() {
		return R.layout.activity_nearby_search;
	}

	@Override
	public void initView() {

		mLstViewItem = (ListView)findViewById(R.id.lst_place_nearby);
		mTxtNoResult = (CustomTextView)findViewById(R.id.txt_search_no_result);
		mBtnExpand = (CustomButton)findViewById(R.id.btn_expand_map);
		mFrameMap = (FrameLayout)findViewById(R.id.frame_map);
		mLLMap = (LinearLayout)findViewById(R.id.ll_map_layout);
		
		mBtnExpand.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				if(!isExpand) {
					mLstViewItem.setVisibility(View.GONE);
					mTxtNoResult.setVisibility(View.GONE);
					mBtnExpand.setBackgroundResource(R.drawable.icon_collapse_64);
					LinearLayout.LayoutParams lpr = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
					mFrameMap.setLayoutParams(lpr);
					ScaleAnimation scaleAnimation = new ScaleAnimation(1f, 1f, 0.5f, 1f, 
							ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
							ScaleAnimation.RELATIVE_TO_SELF, 0f);
					scaleAnimation.setDuration(600);
					mLLMap.startAnimation(scaleAnimation);
					isExpand = true;
				} else {
					mBtnExpand.setBackgroundResource(R.drawable.icon_expand_64);
					ScaleAnimation scaleAnimation = new ScaleAnimation(1f, 1f, 2f, 1f, 
							ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
							ScaleAnimation.RELATIVE_TO_SELF, 0f);
					scaleAnimation.setDuration(600);
					mFrameMap.startAnimation(scaleAnimation);
					LinearLayout.LayoutParams lpr = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,0,1);
					mFrameMap.setLayoutParams(lpr);
					mLstViewItem.setVisibility(View.VISIBLE);
					isExpand = false;
				}
			}
		});
	}

	@Override
	public String getTitleBarTitle() {
		return mContext.getString(R.string.title_nearby_search);
	}

	@Override
	public int getMapViewId() {
		return R.id.map_nearby_search;
	}

}
